<script setup lang="ts">
import Icon from "./Icon.vue";

interface MenuItem {
  title: string;
  index: string | number;
  children?: MenuItem[];
}

const props = defineProps<{
  menus: MenuItem[];
}>();

const height = 38;

const active = defineModel<string | number>();

const MenuLi = defineComponent(
  (
    props: {
      index: number;
      active: string | number;
      source: MenuItem;
    },
    { emit }
  ) => {
    const isOpen = ref(false);

    return () => {
      const { source, index, active } = props;
      const length = source.children?.length || 0;

      return h("li", { key: source.index }, [
        h(
          "div",
          {
            class: `menu-item hover:bg-#F5F5F5 cursor-pointer ${
              active === source.index ? "bg-#F5F5F5" : ""
            }`,
            style: { "--menu-level": index },
            onClick: () => {
              isOpen.value = !isOpen.value;
              if (length == 0) {
                emit("change", source.index);
              }
            },
          },
          [
            h("span", source.title),
            length > 0
              ? h(Icon, {
                  name: "ArrowBottom",
                  class: `text-9px! duration-200 ${
                    isOpen.value ? "rotate-180" : ""
                  }`,
                })
              : null,
          ]
        ),
        length > 0
          ? h(MenuNode, {
              menus: source.children,
              index: index + 1,
              active,
              onChange: (val) => emit("change", val),
              style: {
                height: isOpen.value ? length * height + "px" : "0",
              },
            })
          : null,
      ]);
    };
  },
  {
    props: ["source", "index", "active"],
    emits: ["change"],
  }
);

const MenuNode = defineComponent(
  (props, { emit }) => {
    return () => {
      const { active, menus, index = 1 } = props;

      const nodes = menus.map((e: MenuItem) => {
        return h(MenuLi, {
          source: e,
          active,
          index,
          onChange: (val) => emit("change", val),
        });
      });

      return h(
        "ui",
        {
          class: "block list-none overflow-hidden duration-200 ",
        },
        nodes
      );
    };
  },
  {
    props: ["menus", "index", "active"],
    emits: ["change"],
  }
);
</script>

<template>
  <div>
    <MenuNode
      :menus="menus"
      :index="1"
      :active="active"
      @change="active = $event"
    />
  </div>
</template>

<style lang="less">
.menu-item {
  --menu-level: 1;

  display: flex;
  align-items: center;
  justify-content: space-between;

  height: 38px;
  padding: 0 16px;
  padding-left: calc(var(--menu-level) * 16px);
  font-size: 12px;
}
</style>
